from MineAgent import MineAgent
from MineMove import MineMove
from MineInfo import MineInfo
from Board import Board
from BoardCell import BoardCell
from BoardCSP import BoardCSP
from csp import *
from random import *

class SandboxAgent(MineAgent):

    def __init__(self):
        self.moveStack = []
        self.initialMove = False;
        self.opened = None
        self.tryPeeking = True

    def startNewGame(self,numPlayers, playerID,
                     xSize,ySize,
                     deadCost,peekCost):
        self.board = Board(ySize,xSize)
        return True

    def getNextMove(self):
        mineMove = MineMove(MineMove.OPEN_SQUARE)
        # Make inital move
        if not self.initialMove:
            (mineMove.Y, mineMove.X) = self.board.randomSquare()
            self.initialMove = True
            return mineMove

        # Check if stack has moves
        move = self.makeMoveFromMoveStack()
        if move: return move

        # Try to find safe squares
        ss = self.board.safeSquares()
        if len(ss) > 0:
            self.moveStack += ss
            
        # Check if there are any moves
        move = self.makeMoveFromMoveStack()
        if move: return move

        # Try to solve with CSP
        csp = BoardCSP(self.board)
        print "Thinking...."
        mineMove = MineMove(MineMove.OPEN_SQUARE)
        csp = BoardCSP(self.board,mcv=True,fc=True,mac=True)

        while csp.nextFringe() == True:
            solution = backtracking_search(csp)
            if solution:
                for var in solution:
                    safe = var.getSafe(solution)
                    if len(safe) > 0: 
                        (mineMove.Y, mineMove.X) = safe[randrange(len(safe))]
                        print "Done thinking!"
                        return mineMove
        print "Done thinking!"
        
        # Check again
        move = self.makeMoveFromMoveStack()
        if move: return move
        
        print "Making random move"
        # Else make random move for now
        mineMove = MineMove(MineMove.OPEN_SQUARE)
        (mineMove.Y, mineMove.X) = self.board.randomSquare()
        return mineMove

    def makeMoveFromMoveStack(self):
        if len(self.moveStack) == 0:
            return None
        mineMove = MineMove(MineMove.OPEN_SQUARE)
        (mineMove.Y, mineMove.X) = self.moveStack[-1]
        self.moveStack = self.moveStack[:-1]
        return mineMove
      

    def handleInfo(self,mineInfo):
        if mineInfo.infoType == MineInfo.ALREADY_PEEKED:
            self.tryPeeking = False
            print "Not allowed to peek anymore"
        elif mineInfo.infoType == -2: # Initial mine
            self.board[mineInfo.Y][mineInfo.X] = BoardCell(self.board.Mine)
        elif mineInfo.infoType == MineInfo.SQUARE_INFO:
            cell = BoardCell(mineInfo.value)
            cell.coordinate = (mineInfo.Y,mineInfo.X)
            self.board[mineInfo.Y][mineInfo.X] = cell
